package 中等.多线程;

/**
 * 给你一个类：
 * class FooBar {
 * public void foo() {
 *     for (int i = 0; i < n; i++) {
 *       print("foo");
 *     }
 * }
 * <p>
 * public void bar() {
 *     for (int i = 0; i < n; i++) {
 *       print("bar");
 *     }
 * }
 * }
 * 两个不同的线程将会共用一个 FooBar 实例：
 * <p>
 * 线程 A 将会调用 foo() 方法，而
 * 线程 B 将会调用 bar() 方法
 * 请设计修改程序，以确保 "foobar" 被输出 n 次。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/print-foobar-alternately
 */
public class 交替打印FooBar_1115 {

    public static void main(String[] args) {

    }

}

/**
 * 使用一个变量存储当前需要打印什么值，如果线程打印的顺序不对，那么
 * wait()，释放锁，如果打算顺序时对的，那么唤醒另外一个线程来争夺锁
 */
class FooBar {

    private Object lock = new Object();

    private boolean isFoo = true;

    private int n;

    public FooBar(int n) {
        this.n = n;
    }

    public void foo(Runnable printFoo) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            synchronized (lock) {
                if (!isFoo) lock.wait();
                printFoo.run();
                isFoo = false;
                lock.notify();
            }
        }
    }

    public void bar(Runnable printBar) throws InterruptedException {
        for (int i = 0; i < n; i++) {
            synchronized (lock) {
                if (isFoo) lock.wait();
                printBar.run();
                isFoo = true;
                lock.notify();
            }
        }
    }
}